# 开发debug
30 秒速记
node --inspect index.js打开调试端口,默认127.0.0.1:9229Chrome打开chrome://inspect,或点DevTools里的绿色Node图标连接- 想停在第一行用
--inspect-brk,启动阶段的代码才来得及打断点 VS Code用launch.json或「JavaScript Debug Terminal」调试更顺手- 别把
--inspect=0.0.0.0暴露到公网,连上调试端口等于能执行任意代码
调试 Node 最直接的办法是用 --inspect 启动,让进程开一个调试端口,再用 Chrome DevTools 连上去,像调前端页面一样打断点、看变量。 默认监听 127.0.0.1:9229,打开 chrome://inspect 就能看到目标进程。代码在启动时就执行完的话来不及打断点,这时用 --inspect-brk,进程会停在第一行等你。日常开发我更多在 VS Code 里调,原理一样,都是走 Inspector 协议。要注意调试端口绝不能开到公网,它能直接执行任意代码。
理解「开发debug」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。
工程中还要验证退出码、资源清理和异常输入。属于 testing 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。
Node 调试的底层是 V8 Inspector 协议:--inspect 让进程起一个 WebSocket 服务,调试器(Chrome DevTools、VS Code)连上去后通过它下发断点、单步、读取变量这些指令。常用的几种启动方式:
node --inspect index.js # 开调试端口,代码照常运行
node --inspect-brk index.js # 开调试端口,并停在第一行
node --inspect=9230 index.js # 换端口,多个服务同时调试时用
nodemon --inspect index.js # 改代码自动重启,配合专用 DevTools 窗口自动重连
VS Code 里最省事的是打开「JavaScript Debug Terminal」,在这个终端里跑 npm run dev,会自动挂上调试器,不用写配置。环境要求方面,--inspect 从 Node 6.3 开始提供,Node 8 起移除了旧的 --debug,现在所有在维护的 Node 版本都可以直接用。安全上要记住:调试端口能执行任意代码,默认绑 127.0.0.1 就是为了不让外部访问,改成 0.0.0.0 只能出现在本地容器开发里。
面试官追问
追问 1启动阶段的初始化代码打不上断点,一运行就过去了,怎么办?
换成 node --inspect-brk index.js,进程会停在第一行等调试器连上,这时再打断点然后继续执行。
追问 2服务跑在 Docker 里,本机 Chrome 连不上调试端口,为什么?
--inspect 默认只监听容器内的 127.0.0.1,要改成 --inspect=0.0.0.0:9229 并映射端口 -p 9229:9229。只在本地开发这么做,线上环境不要开。
追问 3用 nodemon 自动重启,每次重启都要重新连调试器,烦不烦?
nodemon --inspect index.js 就行,chrome://inspect 里点「Open dedicated DevTools for Node」打开的专用窗口会在进程重启后自动重连。
追问 4线上进程 CPU 飙高,能直接 --inspect 上去打断点吗?
不建议,断点会让整个进程停住,所有请求都卡死。线上一般是抓 CPU profile 或堆快照带回本地分析,比如用 node --cpu-prof 或者给进程发 SIGUSR1 临时开启 Inspector,抓完立刻关。
# 开发debug
# 快速开始
30 秒速记
- 三步:
node --inspect index.js启动 → 终端打印Debugger listening on ws://...→Chrome里连上 - 连接入口:
DevTools左上角绿色Node图标,或者chrome://inspect的Remote Target - 打开专用调试窗口后,在
Sources面板找到文件打断点,再发请求触发 - 环境:
Node 8+、Chrome 60+就能用,现在的版本都满足 - 终端里的
ws://地址带随机UUID,每次启动都会变,手动连要重新复制
快速上手就三步:用 --inspect 启动服务,在 Chrome 里找到这个 Node 进程打开专用 DevTools,然后在 Sources 面板打断点、发请求触发。 启动后终端会打印一行 Debugger listening on ws://127.0.0.1:9229/...,说明调试端口开好了。打开任意页面的 DevTools,左上角会多出一个绿色的 Node 图标,点它就能进入调试窗口;也可以访问 chrome://inspect 找目标。断点打在路由处理函数里,再用浏览器或 curl 请求一下接口,代码就会停下来,可以看 ctx 里的内容。
理解「快速开始」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。
工程中还要验证退出码、资源清理和异常输入。属于 module 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。
面试官追问
追问 1DevTools 里没看到绿色的 Node 图标,怎么排查?
先看终端有没有打印 Debugger listening,没有就是启动参数没带上。打印了的话打开 chrome://inspect,检查 Configure 里有没有 localhost:9229,端口改过的话要把新端口加进去。
追问 2断点打上了,请求过来却没停,可能是什么原因?
常见是断点打在了 TypeScript 源码或打包产物上但没开 sourcemap,或者请求压根没走到这个分支。可以先在函数第一行写个 debugger;,确认调试器确实生效。
追问 3同时启动两个服务都带 --inspect,第二个报端口占用,怎么办?
默认都抢 9229。给第二个指定端口 --inspect=9230,或者写 --inspect=0 让系统随机分配,终端会打印实际端口。
追问 4断点停在路由里时,怎么查看当前请求的参数?
右侧 Scope 面板直接展开 ctx,看 ctx.query、ctx.request.body;也可以在 Console 里输入 ctx.headers 实时求值,作用域就是当前断点所在的函数。
追问 5调试时日志太多,分不清哪条属于哪个请求,怎么办?
给每个请求注入一个 requestId,用 AsyncLocalStorage 在整条异步链里传递,所有日志都带上它。按 requestId 一过滤,单个请求的完整轨迹就出来了。
# 环境
30 秒速记
- 调试
Koa服务的最低配置:Node.js 8.x+(--inspect已稳定、原生支持async/await)+Chrome 60+(DevTools里有Node入口) Koa 2本身要求Node 7.6+,因为中间件全是async函数- 用到
AsyncLocalStorage的示例要Node 12.17+ / 13.10+,16.4才算稳定,现在直接上Node 18+省心 - 示例代码写的是
import,要么文件叫.mjs,要么package.json里加"type": "module" Chrome只是调试前端界面,代码真正跑在Node进程里,版本以服务端node -v为准
这一节要的就两样东西:Node.js 8.x 以上,Chrome 60 以上。 Node 8 开始 --inspect 调试协议是正式的,Chrome 能直接连上去打断点;Chrome 60 之后 DevTools 左上角会出现一个绿色的 Node 图标,点一下就能打开专门调 Node 的窗口。要注意的是这只是调试本身的门槛,后面用到 AsyncLocalStorage 的例子至少要 Node 12.17,所以我一般建议直接装个 Node 18 或 20 的 LTS 版本,再用 nvm 按项目切版本。
- node环境 8.x +
- chrome 60+
理解「环境」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。
工程中还要验证退出码、资源清理和异常输入。属于 module 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。
调试环境可以拆成两半来理解:被调试的一方是 Node 进程,负责真正执行代码;调试界面的一方是 Chrome DevTools 或 VS Code,负责显示源码、断点和变量。两者之间走的是 Inspector
